#pragma once
#include <stdio.h>
#include <io.h>
#include <debugapi.h>

static int g_debugBreak;

void LogIntoKMD(char *str);

#define DEBUG_UMD

#ifdef DEBUG_UMD

#define MYLOG(...) \
    do { \
        char str2[512] = { 0 }; \
        sprintf(str2, "%s: %s", __func__, __VA_ARGS__); \
        OutputDebugStringA(str2);         \
    } while (0)
#else

#define MYLOG(...)

#endif

#define TRACE_LEVEL_NONE  0
#define TRACE_LEVEL_FATAL 1
#define TRACE_LEVEL_ERROR 2
#define TRACE_LEVEL_WARN  3
#define TRACE_LEVEL_INFO  4
#define TRACE_LEVEL_DEFAULT TRACE_LEVEL_ERROR

#define _LOGMSG(_l, _f, ...) do {    \
    if (_l <= TRACE_LEVEL_DEFAULT) {  \
        char str1[512];               \
        sprintf(str1, _f, ## __VA_ARGS__); \
        MYLOG(str1);   \
    }   \
} while (0)

#define LOGKMD(fmt, ...) do {    \
    char str1[512];               \
    sprintf(str1, fmt, ## __VA_ARGS__); \
    LogIntoKMD(str1);    \
} while (0)

#define LOGF(fmt, ...) \
    _LOGMSG(TRACE_LEVEL_FATAL, fmt, ## __VA_ARGS__)
#define LOGE(fmt, ...) \
    _LOGMSG(TRACE_LEVEL_ERROR, fmt, ## __VA_ARGS__)
#define LOGW(fmt, ...) \
    _LOGMSG(TRACE_LEVEL_WARN, fmt, ## __VA_ARGS__)
#define LOGI(fmt, ...) \
    _LOGMSG(TRACE_LEVEL_INFO, fmt, ## __VA_ARGS__)

#define MYLOG_WRAPPER(...) do { \
    LOGI(__VA_ARGS__);          \
} while (0)

#define LOG_EXACT(_a) MYLOG_WRAPPER##_a
#define MY_LOG(_a) MYLOG_WRAPPER##_a

#define LogFunc(_a) MY_LOG(_a)
#define LogFlow(_a) MY_LOG(_a)
#define LogFlowFunc(_a) MY_LOG(_a)

/** Shortcut to |LogFlowFunc ("ENTER\n")|, marks the beginnig of the function. */
#define LogFlowFuncEnter()      LogFunc(("ENTER\n"))
/** Shortcut to |LogFlowFunc ("LEAVE\n")|, marks the end of the function. */
#define LogFlowFuncLeave()      LogFunc(("LEAVE\n"))
/** Shortcut to |LogFlowFunc ("LEAVE: %Rrc\n")|, marks the end of the function. */
#define LogFlowFuncLeaveRC(rc)  LogFunc(("LEAVE: %Rrc\n", (rc)))
